package com.meida.module.arc.provider.handler;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.meida.common.base.entity.EntityMap;
import com.meida.common.base.module.ExportField;
import com.meida.common.base.module.MyExportParams;
import com.meida.common.base.utils.FlymeUtils;
import com.meida.common.mybatis.interceptor.ExportInterceptor;
import com.meida.common.mybatis.model.ResultBody;
import com.meida.common.security.OpenHelper;
import com.meida.common.thread.IThreadPoolExecutorService;
import com.meida.common.utils.ApiAssert;
import com.meida.common.utils.RedisUtils;
import com.meida.module.arc.client.constants.ArchiveConstants;
import com.meida.module.arc.client.entity.ArcCategory;
import com.meida.module.arc.client.entity.ArcField;
import com.meida.module.arc.client.entity.ArcOriginal;
import com.meida.module.arc.client.vo.ArcWaterMarkJson;
import com.meida.module.arc.provider.service.*;
import com.meida.module.arc.provider.util.FileWaterMarkUtil;
import com.meida.module.file.client.vo.OssSetting;
import com.meida.module.file.provider.oss.client.MioClient;
import com.meida.module.system.client.entity.SysDept;
import com.meida.module.system.provider.service.SysDeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <b>功能名：ArcInfoExportHandler</b><br>
 * <b>说明：</b><br>
 * <b>著作权：</b> Copyright (C) 2021 HUIFANEDU  CORPORATION<br>
 * <b>修改履历：
 *
 * @author 2022-02-11 jiabing
 */
@Service("arcInfoExportHandler")
@Transactional(rollbackFor = Exception.class)
@DS("sharding")
public class ArcInfoExportHandler implements ExportInterceptor {

    @Autowired
    private SysDeptService sysDeptService;

    @Autowired
    private ArcInfoService arcInfoService;

    @Autowired
    private ArcCategoryService arcCategoryService;

    @Autowired
    private IThreadPoolExecutorService threadPoolExecutorService;

    @Autowired
    private ArcOriginalService originalService;

    @Value("${meida.uploadFolder:''}")
    private String uploadFolder;

    @Autowired
    public RedisUtils redisUtils;

    @Override
    public void initExcelExportEntity(ExportField exportField, List list) {
        if (FlymeUtils.isEmpty(exportField)) {
            //根据门类查询 导出的字段列表
            ServletRequestAttributes servletRequestAttributes =
                    (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = servletRequestAttributes.getRequest();
            Map param = (Map) request.getAttribute("reqParam");
            Object categoryId = param.get("categoryId");
            ApiAssert.isNotEmpty("门类id为空", categoryId);
            List<ArcField> fields = arcFieldService.listByCategoryId(Long.parseLong(categoryId.toString()));
//                ExportField oraginalCount = new ExportField();
//                oraginalCount.setEntityName("原文数量");
//                oraginalCount.setKey(item.getFieldName());
//                oraginalCount.setName("原文数量");
//                oraginalCount.setStatistics(false);
//                list.add(oraginalCount);
            fields.stream().filter(field -> {
                return field.getOutIsShow() == 1;
            }).sorted(Comparator.comparing(ArcField::getOutSeq))
                    .forEach(item -> {
                        ExportField obj = new ExportField();
                        obj.setEntityName(item.getFieldCnName());
                        obj.setKey(item.getFieldName());
                        obj.setName(item.getFieldCnName());
                        obj.setStatistics(false);
                        if (FlymeUtils.isNotEmpty(item.getDictCode())) {
                            obj.setDict("arcDict");
                        }
                        if (item.getFieldName().equals("unitId")) {
                            obj.setDict("unitId");
                        }
                        if (item.getFieldName().equals("isCompilation")) {
                            obj.setKey("compilationName");
                        }
                        if (item.getFieldName().equals("isStore") || item.getFieldName().equals("storeRoomId")) {
                            obj.setKey("storeLocationName");
                        }
                        list.add(obj);
                    });
        }
    }

    @Autowired
    private ArcFieldService arcFieldService;

    @Autowired
    private ArcDictService arcDictService;

    @Autowired
    private MioClient mioClient;


    @Override
    public void initExportParams(MyExportParams exportParams) {
        ServletRequestAttributes servletRequestAttributes =
                (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = servletRequestAttributes.getRequest();
        Map param = (Map) request.getAttribute("reqParam");
        Object categoryId = param.get("categoryId");
        ApiAssert.isNotEmpty("门类id不能为空", categoryId);
        ArcCategory category = this.arcCategoryService.getById(Long.parseLong(categoryId.toString()));
        //初始化字典
        Map dictQueryMap = new HashMap();
        dictQueryMap.put("qzId", category.getQzId());
        ResultBody result = arcDictService.listEntityMap(dictQueryMap);
        List<EntityMap> dictList = (List) result.getData();
        Map<String, Map<String, Object>> dictMap = new HashMap<>();

        Map dbDict = dictList.stream().filter(item -> {
            return FlymeUtils.isNotEmpty(item.get("dictCode")) && FlymeUtils.isNotEmpty(item.get("dictName"));
        }).collect(Collectors.toMap(item -> {
            return item.get("dictCode").toString();
        }, item -> {
            return item.get("dictName").toString();
        }, (k1, k2) -> k1));
        dictMap.put("arcDict", dbDict);

        //初始化机构名称字典
        QueryWrapper<SysDept> query = new QueryWrapper();
        query.lambda().eq(SysDept::getCompanyId, category.getQzId());
        List<SysDept> deptList = this.sysDeptService.list(query);
        dictMap.put("unitId", deptList.stream().collect(Collectors.toMap(item -> {
            return item.getDeptId().toString();
        }, item -> {
            return item.getDeptName();
        })));
        exportParams.setDictHandler(new ExportDictHandler(dictMap));
//        Object categoryId = params.get("categoryId");
//        ApiAssert.isNotEmpty("门类id不能为空",categoryId);
//        ArcCategory category = arcCategoryService.getById(Long.parseLong(categoryId.toString()));
//        exportParams.setFileName(category.getCnName()+ DateUtil.format(new Date(),"yyyyMMddHHmmss"));
    }


    @Override
    public ResultBody initData(Map params) {
        Object exportType = params.get("exportType");
        ResultBody resultBody;
        if ("all".equals(exportType)) {
            resultBody = arcInfoService.listEntityMap(params);
        } else {
            resultBody = ResultBody.ok(((Map) arcInfoService.pageList(params).getData()).get("records"));
        }
        List<Map> list=(List<Map>)resultBody.getData();
        if(FlymeUtils.isEmpty(list)){
            return ResultBody.failed("");
        }
        //((List<Map>) resultBody.getData()).stream().map(item -> Long.parseLong(item.get("arcInfoId").toString())).collect(Collectors.toList());
        Map<Long,Object> arcInfoIds = list.stream().collect(Collectors.toMap(item->{
            return (Long) item.get("arcInfoId");
        },item->{
            Object  value  = item.get("arcNo");
            if(FlymeUtils.isEmpty(value)){
                value=item.get("maintitle");//题名
            }
            if(FlymeUtils.isEmpty(value)){
                value = item.get("arcInfoId");
            }
            return value;
        }));
        //异步调用原文导出
        if("1".equals(params.get("original"))){
            params.put("userId", OpenHelper.getUserId());
            threadPoolExecutorService.singleExecute(() -> download(arcInfoIds, params));
        }

        return resultBody;
    }

    /**
     * 下载原文
     *
     * @param arcInfoIdsMap
     * @param params
     */
    private void download(Map<Long, Object> arcInfoIdsMap, Map params) {
        EntityMap map = new EntityMap(params);
        Long categoryId = map.getLong("categoryId");
        String pathDir = map.get("pathDir");
        List<Long> arcInfoIds = new ArrayList<>();
        arcInfoIds.addAll(arcInfoIdsMap.keySet());
        OssSetting ossSetting = mioClient.getOssSetting();
        List<ArcOriginal> list = originalService.listByArcInfoIds(arcInfoIds, categoryId);
        if (FlymeUtils.isNotEmpty(list)) {
            for (ArcOriginal arcOriginal : list) {

                String localPath = arcOriginal.getLocalPath();
                if (FlymeUtils.isNotEmpty(localPath)) {
                    localPath = localPath.replace(ossSetting.getFilePath()+"/archive/", "");
                    String targetPath=pathDir  +"/"+arcInfoIdsMap.get(arcOriginal.getArcInfoId())+"/" + localPath;
                    Object obj = redisUtils.get(ArchiveConstants.REDIS_SETTING_KEY_PREFIX);
                    Map objMap = (Map) obj;
                    String customExpand = MapUtil.getStr(objMap, "customExpand");
                    ArcWaterMarkJson arcWaterMarkJson = JSONObject.parseObject(customExpand, ArcWaterMarkJson.class);
                    // 原文导出是否加水印
                    boolean downloadWaterMark = arcWaterMarkJson.getOriginal().contains("export");
                    //PDF添加水印
                    if (downloadWaterMark && "pdf".equals(arcOriginal.getFileType())) {
                        localPath = handlerWaterMark(localPath, map.getLong("userId"), arcOriginal, arcWaterMarkJson);
                        mioClient.uploadByPath(localPath, targetPath);
                    } else {
                        mioClient.copyObject(ossSetting.getBucket(), localPath, ossSetting.getBucket(), targetPath);
                    }

                }
            }
        }
    }

    //处理水印
    private String handlerWaterMark(String localPath, Long userId, ArcOriginal t, ArcWaterMarkJson arcWaterMarkJson) {
        String footer = DateUtil.format(DateUtil.date(), "yyyy年MM月dd日 E HH时mm分ss秒 ") + " ID: " + userId;
        boolean footerFlag = "1".equals(arcWaterMarkJson.getFooter());

        int img = 0, text = 0;
        float fillOpacity = 0;
        String waterMarkPlus = "";

        fillOpacity = Float.valueOf(arcWaterMarkJson.getTransparent() * 0.01 + "");
        img = arcWaterMarkJson.getImg();
        text = arcWaterMarkJson.getText();
        if (arcWaterMarkJson.getTextContent().uuid == 1) {
            waterMarkPlus = userId + "";
        }
        if (arcWaterMarkJson.getTextContent().date == 1) {
            waterMarkPlus = DateUtil.formatDateTime(DateUtil.date()).replace("-", "/").replace(":", "/").replace(" ", "/" + DateUtil.thisDayOfWeekEnum().toChinese() + "/");
        }

        try {
            // 获取临时目录
            String tempDir = uploadFolder + IdWorker.getIdStr() + "/";
            FileUtil.mkdir(tempDir);

            //文件名（包含后缀名，如：测试.pdf）
            String name = t.getFileName();
            //本地文件路径（绝对路径，包含后缀名，如：F:\\test\\测试.pdf），这里是在windows上测试的，路径是反斜杠
            String path = tempDir + name;
            if (FileUtil.isFile(t.getLocalPath())) {
                path = t.getLocalPath();

                String out = path.split("\\.")[0] + "watermark" + "." + path.split("\\.")[1];
                if (img == 1 && text == 1) {
                    out = FileWaterMarkUtil.PDFAddTextImgWatermark(path, out, arcWaterMarkJson.getTextContent().value, waterMarkPlus, fillOpacity, arcWaterMarkJson.getTextContent().font, arcWaterMarkJson.getTextContent().rotate, arcWaterMarkJson.getImgContent().imgUrl, footerFlag, footer);
                } else if (img == 0 && text == 1) {
                    out = FileWaterMarkUtil.PDFAddWatermark(path, out, arcWaterMarkJson.getTextContent().value, waterMarkPlus, fillOpacity, arcWaterMarkJson.getTextContent().font, arcWaterMarkJson.getTextContent().rotate, footerFlag, footer);
                } else if (img == 1 && text == 0) {
                    out = FileWaterMarkUtil.PDFAddImgWaterMaker(path, out, arcWaterMarkJson.getImgContent().imgUrl, fillOpacity, arcWaterMarkJson.getTextContent().rotate, footerFlag, footer);
                } else if (footerFlag && img == 0 && text == 0) {
                    out = FileWaterMarkUtil.PDFAddFooter(out.replace("watermark", ""), out, footer);
                }
                if (!footerFlag && img == 0 && text == 0) {
                    out = path;
                }
                localPath = out;

                return localPath;
            } else {
                HttpUtil.downloadFile(t.getOssPath(), path);
                if (t.getFileType().equals("pdf") || t.getFileType().equals("ofd0")) {
                    String out = path.split("\\.")[0] + "watermark" + "." + path.split("\\.")[1];
                    if (img == 1 && text == 1) {
                        out = FileWaterMarkUtil.PDFAddTextImgWatermark(path, out, arcWaterMarkJson.getTextContent().value, waterMarkPlus, fillOpacity, arcWaterMarkJson.getTextContent().font, arcWaterMarkJson.getTextContent().rotate, arcWaterMarkJson.getImgContent().imgUrl, footerFlag, footer);
                    } else if (img == 0 && text == 1) {
                        out = FileWaterMarkUtil.PDFAddWatermark(path, out, arcWaterMarkJson.getTextContent().value, waterMarkPlus, fillOpacity, arcWaterMarkJson.getTextContent().font, arcWaterMarkJson.getTextContent().rotate, footerFlag, footer);
                    } else if (img == 1 && text == 0) {
                        out = FileWaterMarkUtil.PDFAddImgWaterMaker(path, out, arcWaterMarkJson.getImgContent().imgUrl, fillOpacity, arcWaterMarkJson.getTextContent().rotate, footerFlag, footer);
                    } else if (footerFlag && img == 0 && text == 0) {
                        out = FileWaterMarkUtil.PDFAddFooter(out.replace("watermark", ""), out, footer);
                    }
                    if (!footerFlag && img == 0 && text == 0) {
                        out = path;
                    }

                    localPath = out;
                }

                return localPath;

            }

        } catch (Exception e) {
            return localPath;
        }
    }

    /**
     * 当serverPath不为空时文件存储到minio服务器
     * @param params
     * @return
     */
    @Override
    public String serverPath(Map params) {
        return uploadFolder;
        //EntityMap map = new EntityMap(params);
        //String exportType = map.get("exportType");
        //return "D:/";
        //return ArcUtils.getRootTempPath()+"/";
//        if (FlymeUtils.isNotEmpty(exportType) && exportType.equals("all")) {
//            return "D:/";
//        } else {
//            return "";
//        }
    }

    /**
     *
     * @param params 参数
     * @param exportName 文件服务器路径
     * @param fileKey 文件名
     * @return
     */
    @Override
    public Boolean exportSuccess(Map params, String exportName, String fileKey) {
        EntityMap map = new EntityMap(params);
        String pathDir = map.get("pathDir");
        //上传文件到minio
        mioClient.uploadByPath(exportName, pathDir + "/" + fileKey);
        return true;
    }
}
